#include "PluginSystem.h"
#include <HLString.h>
#include <LuaManager.h>
#include <JSONManager.h>
#include <sigar.h>
#include <Windows.h>
#include <WinReg.h>

PluginSystem::PluginSystem()
{
}

PluginSystem::~PluginSystem()
{
}

int PluginSystem::Init()
{
	LuaManager::GetInstance().GetLua().new_usertype<PluginSystem>("PluginSystem",
		sol::constructors<PluginSystem()>(),
		"GetName", &PluginSystem::GetName,
		"GetUser", &PluginSystem::GetUser,
		"GetOS", &PluginSystem::GetOS,
		"GetIP", &PluginSystem::GetIP,
		"GetInfo", &PluginSystem::GetInfo,
		"GetSoftList", &PluginSystem::GetSoftList
		);

	return 1;
}

int PluginSystem::Shutdown()
{
	return 1;
}

std::string PluginSystem::GetName()
{
	char szBuffer[1024] = { 0 };
	DWORD dwNameLen = sizeof(szBuffer);
	if (!GetComputerName(szBuffer, &dwNameLen)) return NULL;
	std::string strOutUTF8 = HL::String::GBKToUTF8(szBuffer);
	return strOutUTF8;
}

std::string PluginSystem::GetUser()
{
	char szBuffer[1024] = { 0 };
	DWORD dwSize = sizeof(szBuffer);
	if (!GetUserName(szBuffer, &dwSize)) return NULL;
	std::string strOutUTF8 = HL::String::GBKToUTF8(szBuffer);
	return strOutUTF8;
}

std::string PluginSystem::GetOS()
{
	HKEY hKey;
	LONG nRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hKey);
	if (nRet != ERROR_SUCCESS) return NULL;

	char tmp[1024] = { 0 };

	char szProductName[1024] = { 0 };
	DWORD dwSize = sizeof(szProductName);
	if (RegQueryValueEx(hKey, "ProductName", NULL, NULL, (BYTE *)szProductName, &dwSize) == ERROR_SUCCESS)
		sprintf_s(tmp, "%s", szProductName);

	char szCurrentVersion[1024] = { 0 };
	dwSize = sizeof(szCurrentVersion);
	if (RegQueryValueEx(hKey, "CurrentVersion", NULL, NULL, (BYTE *)szCurrentVersion, &dwSize) == ERROR_SUCCESS)
		sprintf_s(tmp, "%s %s", tmp, szCurrentVersion);

	char szReleaseId[1024] = { 0 };
	dwSize = sizeof(szReleaseId);
	if (RegQueryValueEx(hKey, "ReleaseId", NULL, NULL, (BYTE *)szReleaseId, &dwSize) == ERROR_SUCCESS)
		sprintf_s(tmp, "%s.%s", tmp, szReleaseId);

	char szCurrentBuild[1024] = { 0 };
	dwSize = sizeof(szCurrentBuild);
	if (RegQueryValueEx(hKey, "CurrentBuild", NULL, NULL, (BYTE *)szCurrentBuild, &dwSize) == ERROR_SUCCESS)
		sprintf_s(tmp, "%s.%s", tmp, szCurrentBuild);

	RegCloseKey(hKey);

	std::string strOutUTF8 = HL::String::GBKToUTF8(tmp);
	return strOutUTF8;
}

int getIP(sigar_t *sigar, sigar_uint32_t address, char *addr_str)
{
	char *next = addr_str;
	int n = 0;
	const unsigned char *src = (const unsigned char *)&address;

	do {
		unsigned char u = *src++;
		if (u > 99) {
			*next++ = '0' + u / 100;
			u %= 100;
			*next++ = '0' + u / 10;
			u %= 10;
		}
		else if (u > 9) {
			*next++ = '0' + u / 10;
			u %= 10;
		}
		*next++ = '0' + u;
		*next++ = '.';
		n++;
	} while (n < 4);

	*--next = 0;

	return SIGAR_OK;
}

std::string PluginSystem::GetIP()
{
	sigar_t *t = 0;
	sigar_open(&t);

	sigar_net_interface_config_t netconfig;
	sigar_net_interface_config_primary_get(t, &netconfig);

	char tmp[24];
	getIP(t, netconfig.address.addr.in, tmp);

	sigar_close(t);

	std::string strOutUTF8 = HL::String::GBKToUTF8(tmp);
	return strOutUTF8;
}

std::string PluginSystem::GetInfo()
{
	int nID = JSONManager::GetInstance().Create();

	JSONManager::GetInstance().Set(nID, "name", GetName().c_str());
	JSONManager::GetInstance().Set(nID, "user", GetUser().c_str());
	JSONManager::GetInstance().Set(nID, "os", GetOS().c_str());
	JSONManager::GetInstance().Set(nID, "address", GetIP().c_str());

	return JSONManager::GetInstance().Get(nID);
}

std::vector<std::string> PluginSystem::GetSoftList()
{
	std::vector<std::string> vecOut;
	char szKeyName[1024] = { 0 };
	char szDisplayName[1024] = { 0 };
	char szDisplayVersion[1024] = { 0 };
	char szInstallDate[1024] = { 0 };
	char szPublisher[1024] = { 0 };
	DWORD dwKeySize = 1024;
	DWORD dwSize = 1024;
	DWORD dwIndex = 0;
	DWORD dwSystemComponent = 0;
	int nID = JSONManager::GetInstance().Create();

	std::string strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
	HKEY hKey;
	if (RegOpenKeyEx(HKEY_CURRENT_USER, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) != ERROR_SUCCESS) return vecOut;
	LONG nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
	while (nResult == ERROR_SUCCESS)
	{
		strSubKey.append(szKeyName);
		HKEY hSubKey;
		if (RegOpenKeyEx(HKEY_CURRENT_USER, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hSubKey) == ERROR_SUCCESS)
		{
			dwSize = 1024;
			if (RegQueryValueEx(hSubKey, "SystemComponent", NULL, NULL, (BYTE *)dwSystemComponent, &dwSize) == ERROR_SUCCESS)
				if (dwSystemComponent)
				{
					strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
					dwKeySize = 1024;
					dwIndex++;
					nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
					continue;
				}

			dwSize = 1024;
			if (RegQueryValueEx(hSubKey, "DisplayName", NULL, NULL, (BYTE *)szDisplayName, &dwSize) == ERROR_SUCCESS)
				JSONManager::GetInstance().Set(nID, "DisplayName", szDisplayName);
			else
				JSONManager::GetInstance().Set(nID, "DisplayName", "None");

			dwSize = 1024;
			if (RegQueryValueEx(hSubKey, "DisplayVersion", NULL, NULL, (BYTE *)szDisplayVersion, &dwSize) == ERROR_SUCCESS)
				JSONManager::GetInstance().Set(nID, "DisplayVersion", szDisplayVersion);
			else
				JSONManager::GetInstance().Set(nID, "DisplayVersion", "None");

			dwSize = 1024;
			if (RegQueryValueEx(hSubKey, "InstallDate", NULL, NULL, (BYTE *)szInstallDate, &dwSize) == ERROR_SUCCESS)
				JSONManager::GetInstance().Set(nID, "InstallDate", szInstallDate);
			else
				JSONManager::GetInstance().Set(nID, "InstallDate", "None");

			dwSize = 1024;
			if (RegQueryValueEx(hSubKey, "Publisher", NULL, NULL, (BYTE *)szPublisher, &dwSize) == ERROR_SUCCESS)
				JSONManager::GetInstance().Set(nID, "Publisher", szPublisher);
			else
				JSONManager::GetInstance().Set(nID, "Publisher", "None");

			RegCloseKey(hSubKey);
		}
		strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
		dwKeySize = 1024;
		dwIndex++;
		nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
		vecOut.push_back(JSONManager::GetInstance().Get(nID));
	}
	RegCloseKey(hKey);

	strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
	{
		dwKeySize = 1024;
		dwIndex = 0;
		nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
		while (nResult == ERROR_SUCCESS)
		{
			strSubKey.append(szKeyName);
			HKEY hSubKey;
			if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hSubKey) == ERROR_SUCCESS)
			{
				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "SystemComponent", NULL, NULL, (BYTE *)dwSystemComponent, &dwSize) == ERROR_SUCCESS)
					if (dwSystemComponent)
					{
						strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
						dwKeySize = 1024;
						dwIndex++;
						nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
						continue;
					}

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "DisplayName", NULL, NULL, (BYTE *)szDisplayName, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "DisplayName", szDisplayName);
				else
					JSONManager::GetInstance().Set(nID, "DisplayName", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "DisplayVersion", NULL, NULL, (BYTE *)szDisplayVersion, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "DisplayVersion", szDisplayVersion);
				else
					JSONManager::GetInstance().Set(nID, "DisplayVersion", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "InstallDate", NULL, NULL, (BYTE *)szInstallDate, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "InstallDate", szInstallDate);
				else
					JSONManager::GetInstance().Set(nID, "InstallDate", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "Publisher", NULL, NULL, (BYTE *)szPublisher, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "Publisher", szPublisher);
				else
					JSONManager::GetInstance().Set(nID, "Publisher", "None");

				RegCloseKey(hSubKey);
			}
			strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
			dwKeySize = 1024;
			dwIndex++;
			nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
			vecOut.push_back(JSONManager::GetInstance().Get(nID));
		}
		RegCloseKey(hKey);
	}

	strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS)
	{
		dwKeySize = 1024;
		dwIndex = 0;
		nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
		while (nResult == ERROR_SUCCESS)
		{
			strSubKey.append(szKeyName);
			HKEY hSubKey;
			if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strSubKey.c_str(), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_32KEY, &hSubKey) == ERROR_SUCCESS)
			{
				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "SystemComponent", NULL, NULL, (BYTE *)dwSystemComponent, &dwSize) == ERROR_SUCCESS)
					if (dwSystemComponent)
					{
						strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
						dwKeySize = 1024;
						dwIndex++;
						nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
						continue;
					}

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "DisplayName", NULL, NULL, (BYTE *)szDisplayName, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "DisplayName", szDisplayName);
				else
					JSONManager::GetInstance().Set(nID, "DisplayName", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "DisplayVersion", NULL, NULL, (BYTE *)szDisplayVersion, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "DisplayVersion", szDisplayVersion);
				else
					JSONManager::GetInstance().Set(nID, "DisplayVersion", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "InstallDate", NULL, NULL, (BYTE *)szInstallDate, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "InstallDate", szInstallDate);
				else
					JSONManager::GetInstance().Set(nID, "InstallDate", "None");

				dwSize = 1024;
				if (RegQueryValueEx(hSubKey, "Publisher", NULL, NULL, (BYTE *)szPublisher, &dwSize) == ERROR_SUCCESS)
					JSONManager::GetInstance().Set(nID, "Publisher", szPublisher);
				else
					JSONManager::GetInstance().Set(nID, "Publisher", "None");

				RegCloseKey(hSubKey);
			}
			strSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
			dwKeySize = 1024;
			dwIndex++;
			nResult = RegEnumKeyEx(hKey, dwIndex, szKeyName, &dwKeySize, 0, 0, 0, 0);
			vecOut.push_back(JSONManager::GetInstance().Get(nID));
		}
		RegCloseKey(hKey);
	}

	return vecOut;
}
